/*
 * Created on Mar 19, 2005
 * Created by dfhuynh
 */
package edu.mit.simile.longwell.ui.command;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.log4j.Logger;
import org.apache.velocity.VelocityContext;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.rdf.model.impl.PropertyImpl;
import com.hp.hpl.jena.rdf.model.impl.ResourceImpl;
import com.hp.hpl.jena.util.FileManager;
import com.hp.hpl.jena.vocabulary.RDF;
import com.hp.hpl.jena.vocabulary.RDFS;

import edu.mit.simile.longwell.LongwellServer;
import edu.mit.simile.longwell.Profile;

import edu.mit.simile.longwell.login.CheckLogin;
import edu.mit.simile.longwell.query.IAnswer;
import edu.mit.simile.longwell.query.IQueryModel;
import edu.mit.simile.longwell.query.Query;
import edu.mit.simile.longwell.query.QueryException;
import edu.mit.simile.longwell.query.engine.QueryEngine;
import edu.mit.simile.longwell.ui.FlairMessage;
import edu.mit.simile.longwell.ui.InjectionManager;

/**
 * @author dfhuynh
 */
public class ExportCommand extends CommandBase implements IFlairCommand {
	final static private Logger s_logger = Logger.getLogger(ExportCommand.class);
	public ExportCommand(InjectionManager injectionManager) {
		super(injectionManager);
		// TODO Auto-generated constructor stub
		
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.mit.simile.longwell.ui.command.IFlairCommand#execute(edu.mit.simile
	 * .longwell.ui.FlairMessage)
	 */
	public void execute(FlairMessage msg) throws ServletException {
		VelocityContext vcContext = createContext(msg);
		HttpSession session = msg.m_request.getSession();
		FlairMessage message = (FlairMessage) session.getAttribute("mapMsg");

		String format = msg.m_query.getFirstParamValue("format");
		IAnswer answer = null;
		try {
			answer = performQuery(msg, message, vcContext);
		} catch (QueryException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if (format == null) {
			format = "application/xml";
		}
		setContentType(format, msg.m_response);
		/*
		 * String pseudoURI = msg.m_query.getFirstParamValue("pseudoURI"); if
		 * (pseudoURI != null) { exportOne(msg, pseudoURI, format); } else {
		 * exportMany(msg, format); }
		 */
		try {
			exportGMap(msg, message, answer.getObjects());
		} catch (QueryException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		/*
		 * if ("GMap".equals(format)) { try { exportGMap(msg,
		 * message,answer.getObjects()); } catch (QueryException e) { // TODO
		 * Auto-generated catch block e.printStackTrace(); } }
		 */

	}

	protected void exportOne(FlairMessage msg, String pseudoURI, String format)
			throws ServletException {
		Profile profile = msg.getProfile();
		Model model = ModelFactory.createDefaultModel();

		profile.extractObject(
				profile.getSchemaModel().pseudoURIToResource(pseudoURI), model);

		try {
			model.write(msg.m_response.getOutputStream(), format);
		} catch (IOException e) {
			throw new ServletException(e);
		} finally {
			model.close();
		}
	}

	protected void exportMany(FlairMessage msg, String format)
			throws ServletException {
		Profile profile = msg.getProfile();
		Model model = ModelFactory.createDefaultModel();

		try {
			IQueryModel queryModel = (IQueryModel) profile
					.getStructuredModel(IQueryModel.class);

			Set objects = queryModel.queryObjects(msg.m_query, false);
			Iterator i = objects.iterator();
			while (i.hasNext()) {
				Resource r = (Resource) i.next();

				profile.extractObject(r, model);
			}

			model.write(msg.m_response.getOutputStream(), format);
		} catch (Exception e) {
			throw new ServletException(e);
		} finally {
			model.close();
		}
	}

	protected Set getMany(FlairMessage msg) throws ServletException {
		try {
			Profile profile = msg.getProfile();
			QueryEngine queryModel = (QueryEngine) profile
					.getStructuredModel(QueryEngine.class);

			Set objects = queryModel.queryObjects(msg.m_query, false);
			if (objects == null) {
				objects = profile.getSchemaModel().getAllObjects();// getAllItems();
			}

			return objects;
		} catch (Exception e) {
			throw new ServletException(e);
		}
	}

	protected IAnswer performQuery(FlairMessage msg, FlairMessage message,
			VelocityContext vcContext) throws QueryException {
		Query query = msg.m_query;
		// HttpSession session = msg.m_request.getSession();
		// String sessionId = session.getId();
		IQueryModel queryModel = (IQueryModel) msg.getProfileFromSession()
				.getStructuredModel(IQueryModel.class);

		IAnswer answer = queryModel.query(message.m_query, false);

		return answer;
	}

	protected void exportGMap(FlairMessage msg, FlairMessage message,
			Set objects) throws ServletException {

		VelocityContext vcContext = createContext(msg);
		try {

			// String[] properties =
			// StringUtils.splitPreserveAllTokens(msg.m_query.getFirstParamValue("latlong"),
			// ';');
			String property = msg.m_query
					.getFirstParamValue("resultsViewParam");
			if (property == null)
				property = message.m_query
						.getFirstParamValue("resultsViewParam");
			/*
			 * Set<String> propertyURIs = new HashSet<String>();
			 * if(propertyURIs!=null){ for (int i = 0; i < properties.length;
			 * i++) { String property = properties[i]; if (property != null &&
			 * property.length() > 0) { propertyURIs.add(property); } } }
			 */

			List<MapLocation> locations = new ArrayList<MapLocation>();

			Profile profile = msg.getProfileFromSession();
			try {

				// SchemaModel schemaModel = profile.getSchemaModel().;

				double minLatitude = Double.POSITIVE_INFINITY;
				double maxLatitude = Double.NEGATIVE_INFINITY;
				double minLongitude = Double.POSITIVE_INFINITY;
				double maxLongitude = Double.NEGATIVE_INFINITY;

				Map<String, LLRecord> llToRecord = new HashMap<String, LLRecord>();
				Map<String, Integer> typeToCode = new HashMap<String, Integer>();
				int codeMax = 0;

				Iterator i = objects.iterator();

				System.out.println(objects.size());

				while (i.hasNext()) {

					Resource res = (Resource) i.next();

					// URI typeURI =
					// schemaModel.getLearnedClassURIOfItem(object);

					String typeURI = res.getProperty(RDF.type).getObject()
							.toString();

					Integer code = typeToCode.get(typeURI);

					if (code == null) {
						code = new Integer(codeMax++);
						typeToCode.put(typeURI, code);
					}

					// Iterator j = propertyURIs.iterator();
					// while (j.hasNext()) {
					// URI property = (URI) j.next();

					Property prop = new PropertyImpl(property);
					Statement stmt = res.getProperty(prop);

					if (stmt != null) {

						Object result = stmt.getObject();
						String latlong = result.toString();
						if (latlong != null) {
							LLRecord ll = (LLRecord) llToRecord.get(latlong);
							if (ll == null) {
								ll = new LLRecord();
								int comma = latlong.indexOf(',');
								if (comma > 0) {
									try {
										double latitude = Double
												.parseDouble(latlong.substring(
														0, comma));
										double longitude = Double
												.parseDouble(latlong
														.substring(comma + 1));

										if (Double.isNaN(latitude)
												|| Double.isNaN(longitude)) {
											break;
										}

										ll.m_objects = new HashSet<String>();
										ll.m_codes = new HashSet<Integer>();

										minLatitude = Math.min(minLatitude,
												latitude);
										maxLatitude = Math.max(maxLatitude,
												latitude);
										minLongitude = Math.min(minLongitude,
												longitude);
										maxLongitude = Math.max(maxLongitude,
												longitude);

										ll.m_latitude = latitude;
										ll.m_longitude = longitude;
										ll.m_codes.add(code);
									} catch (Exception e) {
										// ignore
									}
								}

								llToRecord.put(latlong, ll);
							}
							if (ll.m_objects != null) {
								ll.m_objects.add(res.getURI());
							}
							// break;
						}
					} else {
						String[] datasets = (String[]) msg.m_request
								.getSession().getAttribute(
										msg.m_request.getSession().getId());
						String dataset = datasets[0];
						prop = new PropertyImpl(
								"http://www.provincia.tn.it/ont/anagrafe.owl#viaResidenza");
						stmt = res.getProperty(prop);
						if (stmt != null) {
							Resource address = stmt.getResource();
							StmtIterator addressStmtit = profile.getModel()
									.listStatements(address, RDFS.label,
											(RDFNode) null);
							while (addressStmtit.hasNext()) {
								Statement addressStmt = addressStmtit.next();
								//chiedo le coordinate al file
								String latlong = coordinatesFromFile(addressStmt
										.getLiteral().toString()
										+ " "
										+ dataset);
								//chiedo le coordinate a google
								/*
								String latlong = coordinatesFromGoogleMap(addressStmt
										.getLiteral().toString()
										+ " "
										+ dataset);
										*/
								if (latlong != null) {
									LLRecord ll = (LLRecord) llToRecord
											.get(latlong);
									if (ll == null) {
										ll = new LLRecord();
										int comma = latlong.indexOf(',');
										if (comma > 0) {
											try {
												double latitude = Double
														.parseDouble(latlong
																.substring(0,
																		comma));
												double longitude = Double
														.parseDouble(latlong
																.substring(comma + 1));

												if (Double.isNaN(latitude)
														|| Double
																.isNaN(longitude)) {
													break;
												}

												ll.m_objects = new HashSet<String>();
												ll.m_codes = new HashSet<Integer>();

												minLatitude = Math.min(
														minLatitude, latitude);
												maxLatitude = Math.max(
														maxLatitude, latitude);
												minLongitude = Math
														.min(minLongitude,
																longitude);
												maxLongitude = Math
														.max(maxLongitude,
																longitude);

												ll.m_latitude = latitude;
												ll.m_longitude = longitude;
												ll.m_codes.add(code);
											} catch (Exception e) {
												// ignore
											}
										}

										llToRecord.put(latlong, ll);
									}
									if (ll.m_objects != null) {
										ll.m_objects.add(res.getURI());
									}
									// break;
								}

							}
						}
					}
				}

				double centerLatitude = (minLatitude + maxLatitude) / 2;
				double centerLongitude = (minLongitude + maxLongitude) / 2;
				double spanLatitude = Math
						.max(0.1, (maxLatitude - minLatitude));
				double spanLongitude = Math.max(0.1,
						(maxLongitude - minLongitude));

				msg.m_response.setContentType("text/xml");
				msg.m_response.setCharacterEncoding("UTF-8");

				vcContext.put("exportType", "GMap");
				vcContext
						.put("centerLatitude", Double.toString(centerLatitude));
				vcContext.put("centerLongitude",
						Double.toString(centerLongitude));

				vcContext.put("spanLatitude", Double.toString(spanLatitude));
				vcContext.put("spanLongitude", Double.toString(spanLongitude));

				// LongwellURL url = new LongwellURL(msg);

				/*
				 * Legend
				 */

				List<LegendEntry> legend = new ArrayList<LegendEntry>();
				i = typeToCode.keySet().iterator();

				while (i.hasNext()) {

					String typeURI = i.next().toString();
					int separator = typeURI.indexOf("#") + 1;
					Integer code = (Integer) typeToCode.get(typeURI);
					String markerURL = msg.m_request.getContextPath()
							+ "/resources/marker?x=0&y=0&s=1&w=40&h=34&label=%20&colorCode="
							+ code.intValue();
					String typeLabel = typeURI.substring(separator);

					legend.add(new LegendEntry(StringEscapeUtils
							.escapeXml(markerURL), typeLabel));

				}

				vcContext.put("legend", legend);

				/*
				 * Individual locations
				 */

				Property rdfType = RDF.type;
				i = llToRecord.keySet().iterator();
				int index = 0;
				while (i.hasNext()) {
					String latlong = (String) i.next();
					LLRecord ll = (LLRecord) llToRecord.get(latlong);
					if (ll.m_objects != null) {
						int objectCount = ll.m_objects.size();
						String markerLabel = objectCount > 1 ? Integer
								.toString(objectCount) : "+";

						String colorCode = "";
						Iterator j = ll.m_codes.iterator();
						while (j.hasNext()) {
							Integer integer = (Integer) j.next();
							if (colorCode.length() > 0) {
								colorCode += ",";
							}
							colorCode += integer;
						}

						String markerURL = msg.m_request.getContextPath()
								+ "/resources/marker?x=0&y=0&s=1&w=40&h=34"
								+ "&label=" + markerLabel + "&colorCode="
								+ colorCode;

						MapLocation location = new MapLocation(index++,
								ll.m_latitude, ll.m_longitude,
								StringEscapeUtils.escapeXml(markerURL));

						Iterator n = ll.m_objects.iterator();

						while (n.hasNext()) {
							Object object = (Object) n.next();
							Resource reso = profile.getModel().createResource(
									object.toString());

							// String label =
							// label;//StringEscapeUtils.escapeXml(objectURI);//schemaModel.getLabel(object,
							// ""));
							String objectURL = StringEscapeUtils.escapeXml(msg
									.getURL(reso));
							/*
							 * StringBuffer editURL = new StringBuffer(); {
							 * editURL.append(url.getContextPath() +
							 * "/resources/forms/?uri=" +
							 * Utilities.encode(objectURI));
							 * 
							 * Iterator types =
							 * profile.getQueryManager().listObjectsOfProperty
							 * (c, object, rdfType).iterator(); while
							 * (types.hasNext()) { URI typeURI = (URI)
							 * types.next(); editURL.append("&amp;type=" +
							 * Utilities.encode(typeURI.toString())); } }
							 * 
							 * LongwellURL removeURL =
							 * url.changeCommandQuery("remove-location", ""); {
							 * removeURL.getQuery().setParameter("objectURI",
							 * objectURI);
							 * removeURL.getQuery().setParameter("latlong",
							 * msg.m_query.getFirstParamValue("latlong")); }
							 */
							MapLocationItem item = new MapLocationItem(
									object.toString(), objectURL, "", "");// editURL.toString(),
																			// StringEscapeUtils.escapeXml(removeURL.toURLString()));
							location.addItem(item);

						}
						locations.add(location);

					}

				}
			} finally {
				// if (c != null) c.close();
			}

			vcContext.put("locations", locations);
			exportPolygons(objects,profile,vcContext);
			// msg.m_ve.mergeTemplate("templates/panes/map-results-pane.vt",
			// vcContext, msg.m_response.getWriter());
			msg.m_ve.mergeTemplate("templates/export/gmap-results.vt",
					vcContext, msg.m_response.getWriter());
			// msg.m_ve.mergeTemplate("templates/commands/export.vt", vcContext,
			// msg.m_response.getWriter());
		} catch (Exception e) {
			throw new ServletException(e);
		}

	}

	private void exportPolygons(Set objects, Profile profile,VelocityContext vcContext) {
		int index = 1;
		List<MapPolygon> polygons = new ArrayList<MapPolygon>();
		Iterator i = objects.iterator();
		Property haPoligono = new PropertyImpl("http://www.okkam.it/ont/particella_catastale.owl#haPoligono");
		Property haVertice = new PropertyImpl("http://www.okkam.it/ont/particella_catastale.owl#haVertice");
		Property haPunto = new PropertyImpl("http://www.okkam.it/ont/particella_catastale.owl#haPunto");
		Property haLat = new PropertyImpl("http://www.okkam.it/ont/particella_catastale.owl#haLatitudineWGS84Decimale");
		Property haLong = new PropertyImpl("http://www.okkam.it/ont/particella_catastale.owl#haLongitudineWGS84Decimale");
		Property haNumeroOrdine = new PropertyImpl("http://www.okkam.it/ont/particella_catastale.owl#haNumeroOrdine");
		Property haNumero = new PropertyImpl("http://www.okkam.it/ont/particella_catastale.owl#haNumero");
		while(i.hasNext()){
			List points = new ArrayList<Point>();
			Resource poligono = (Resource) i.next();
			StmtIterator poligonoStmt = profile.getModel()
					.listStatements(poligono, haPoligono,
							(RDFNode) null);
			if(poligonoStmt.hasNext()){
				Object poligonoObj = poligonoStmt.next().getObject();
				String numeroParticella = profile.getModel()
						.listStatements(poligono, haNumero,
								(RDFNode) null).next().getObject().toString();
						//poligono.getProperty(haNumero).getObject().toString();
				String poligonoString = poligonoObj.toString();
				Resource poligonoRes = new ResourceImpl(poligonoString);

				StmtIterator verticiStmts = profile.getModel()
						.listStatements(poligonoRes, haVertice,
								(RDFNode) null);
				HashMap<Integer, Point> hash = new HashMap<Integer, Point>();
				while(verticiStmts.hasNext()){
					Object verticeObj = verticiStmts.next().getObject();
					Resource verticeRes = new ResourceImpl(verticeObj.toString());
					int numeroOrdineStmt = Integer.parseInt(profile.getModel()
							.listStatements(verticeRes, haNumeroOrdine,
									(RDFNode) null).next().getObject().toString());
					Object puntoStmt = profile.getModel()
							.listStatements(verticeRes, haPunto,
									(RDFNode) null).next().getObject();
					Resource puntoRes = new ResourceImpl(puntoStmt.toString());
					String latitudine = profile.getModel()
							.listStatements(puntoRes, haLat,
									(RDFNode) null).next().getObject().toString();
					String longitudine = profile.getModel()
							.listStatements(puntoRes, haLong,
									(RDFNode) null).next().getObject().toString();
					Point punto = new Point(latitudine,longitudine);
					hash.put(numeroOrdineStmt, punto);
					//points.add(punto);
				}
				 Object[]   key   =     hash.keySet().toArray();  
		         Arrays.sort(key);  
				
				for(int g=0;g<key.length;g++){
					Point p = (Point) hash.get(key[g]);
					points.add(p);
				}
				HashMap<String, List<Point>> pointsForPolygon= new HashMap<String, List<Point>>();
				pointsForPolygon.put(poligonoString, points);
				MapPolygon mapPolygon = new MapPolygon(poligonoString, pointsForPolygon,numeroParticella);
				polygons.add(mapPolygon);
			}
		}
		if(polygons!=null && polygons.size()>0)
			vcContext.put("polygons", polygons);
	}
	
	
	//metodo che cerca l'indirizzo nel file, se lo trova non e' necessario chimare le api google
	private String coordinatesFromFile(String location) throws IOException {
        Properties properties = new Properties();
        File coordinatesFile = new File(LongwellServer.getGeocodingFile());
        FileInputStream fisCoord = null;
        try {
        	fisCoord = new FileInputStream(coordinatesFile);
			properties.load(fisCoord);
			
		} catch (Exception e) {
            System.exit(1);
		}
        
        String locationNorm = location.replace(" ", "_");
        
        String coordinates = properties.getProperty(locationNorm);
        
        //se le coordinate sono nulle le devo scrivere sul file;
        if(coordinates==null){
        	coordinates = saveCoordinatesOnFile(coordinatesFile,properties,location);
        }
        fisCoord.close();
		return coordinates;
	}
	
	private String saveCoordinatesOnFile(File coordinatesFile, Properties prop, String location){
		String coordinates = coordinatesFromGoogleMap(location);
		String locationNorm = location.replace(" ", "_");
		prop.setProperty(locationNorm, coordinates);
		try {
			prop.store(new FileOutputStream(coordinatesFile), null);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return coordinates;
	}
	
	//metodo che risolve l'indirizzo in coordinate chiamato le api google
	private String coordinatesFromGoogleMap(String location) {
		s_logger.info("request to api google for address: "+location);
		if (LongwellServer.getProxyHost() != null
				&& LongwellServer.getProxyHost().length() > 0)
			System.setProperty("http.proxyHost", LongwellServer.getProxyHost());
		if (LongwellServer.getProxyPort() != null
				&& LongwellServer.getProxyPort().length() > 0)
			System.setProperty("http.proxyPort", LongwellServer.getProxyPort());

		JSONObject json = null;
		String latlng = null;
		try {
			String googleApi = "http://maps.googleapis.com/maps/api/geocode/json?address="
					+ location + " TN Italia&sensor=true";
			googleApi = googleApi.replace(" ", "%20");
			// System.out.println(googleApi);
			InputStream is = new URL(googleApi).openStream();

			BufferedReader rd = new BufferedReader(new InputStreamReader(is));
			String jsonText = prepareJson(rd);
			json = new JSONObject(jsonText);

		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		try {

			JSONArray latJsonArray = (JSONArray) json.getJSONArray("results");
			if(latJsonArray.length()>0){
				Double lat = (Double) latJsonArray.getJSONObject(0)
						.getJSONObject("geometry").getJSONObject("location")
						.get("lat");

				Double lng = (Double) latJsonArray.getJSONObject(0)
						.getJSONObject("geometry").getJSONObject("location")
						.get("lng");

				latlng = lat + ", " + lng;				
			}
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return latlng;

	}

	private String prepareJson(Reader rd) {
		StringBuilder sb = new StringBuilder();
		int cp;
		try {
			while ((cp = rd.read()) != -1) {
				sb.append((char) cp);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return sb.toString();

	}

	public class MapPolygon {
		private String m_index;
		private HashMap<String,List<Point>> m_points;
		private String m_infos;

		public MapPolygon(String index, HashMap<String,List<Point>> points, String infos) {
			m_index = index;
			m_points = points;
			m_infos=infos;
		}

		public String getIndex() {
			return m_index;
		}
		public List getVericles(String index){
			return m_points.get(index);
		}
		public String getInfos(){
			return m_infos;
		}
	}

	public class Point {
		private String latitudine;
		private String longitudine;

		public Point(String x, String y) {
			latitudine = x;
			longitudine = y;
		}

		public String getLatitudine() {
			return latitudine;
		}

		public String getLongitudine() {
			return longitudine;
		}
	}

	public class MapLocation {
		private int m_index;
		private double m_latitude;
		private double m_longitude;
		private String m_markerURL;
		private List<MapLocationItem> m_items;

		public MapLocation(int index, double latitude, double longitude,
				String marker) {
			m_items = new ArrayList<MapLocationItem>();
			m_index = index;
			m_latitude = latitude;
			m_longitude = longitude;
			m_markerURL = marker;
		}

		public void addItem(MapLocationItem item) {
			m_items.add(item);
		}

		public double lat() {
			return m_latitude;
		}

		public String getLatitude() {
			return Double.toString(m_latitude);
		}

		public double lng() {
			return m_longitude;
		}

		public String getLongitude() {
			return Double.toString(m_longitude);
		}

		public int getIndex() {
			return m_index;
		}

		public String getMarkerURL() {
			return m_markerURL;
		}

		public List getItems() {
			return m_items;
		}

		public Iterator getItemsIterator() {
			return m_items.iterator();
		}
	}

	public class MapLocationItem {
		private String m_label;
		private String m_itemURL;
		private String m_editURL;
		private String m_removeURL;

		public MapLocationItem(String label, String URL, String editURL,
				String removeURL) {
			m_label = label;
			m_itemURL = URL;
			m_editURL = editURL;
			m_removeURL = removeURL;
		}

		public String getLabel() {
			return m_label;
		}

		public String getItemURL() {
			return m_itemURL;
		}

		public String getEditURL() {
			return m_editURL;
		}

		public String getRemoveURL() {
			return m_removeURL;
		}
	}

	static private class LLRecord {
		double m_latitude;

		double m_longitude;

		Set<String> m_objects;

		Set<Integer> m_codes;
	}

	public class LegendEntry {
		private String m_markerURL;

		private String m_label;

		public LegendEntry(String marker, String label) {
			m_markerURL = marker;
			m_label = label;
		}

		public String getMarkerURL() {
			return m_markerURL;
		}

		public String getLabel() {
			return m_label;
		}
	}

	protected void setContentType(String format, HttpServletResponse response) {
		if ("RDFXML".equals(format)) {
			response.setContentType("application/rdf+xml");
		} else if ("GMap".equals(format)) {
			response.setContentType("application/xml");
		} else if ("N3".equals(format)) {
			response.setContentType("application/n3");
		} else {
			response.setContentType("text/plain");
		}
	}
}
